<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Arithmetic Operations on Images</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d6/d00/tutorial_py_root.html">OpenCV-Python Tutorials</a></li><li class="navelem"><a class="el" href="../../d7/d16/tutorial_py_table_of_contents_core.html">Core Operations</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Arithmetic Operations on Images </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goal </h2>
<ul>
<li>Learn several arithmetic operations on images, like addition, subtraction, bitwise operations, and etc.</li>
<li>Learn these functions: <b><a class="el" href="../../d2/de8/group__core__array.html#ga10ac1bfb180e2cfda1701d06c24fdbd6" title="Calculates the per-element sum of two arrays or an array and a scalar. ">cv.add()</a></b>, <b><a class="el" href="../../d2/de8/group__core__array.html#gafafb2513349db3bcff51f54ee5592a19" title="Calculates the weighted sum of two arrays. ">cv.addWeighted()</a></b>, etc.</li>
</ul>
<h2>Image Addition </h2>
<p>You can add two images with the OpenCV function, <a class="el" href="../../d2/de8/group__core__array.html#ga10ac1bfb180e2cfda1701d06c24fdbd6" title="Calculates the per-element sum of two arrays or an array and a scalar. ">cv.add()</a>, or simply by the numpy operation res = img1 + img2. Both images should be of same depth and type, or the second image can just be a scalar value.</p>
<dl class="section note"><dt>Note</dt><dd>There is a difference between OpenCV addition and Numpy addition. OpenCV addition is a saturated operation while Numpy addition is a modulo operation.</dd></dl>
<p>For example, consider the below sample: </p><div class="fragment"><div class="line">&gt;&gt;&gt; x = np.uint8([250])</div><div class="line">&gt;&gt;&gt; y = np.uint8([10])</div><div class="line"></div><div class="line">&gt;&gt;&gt; <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>( <a class="code" href="../../d2/de8/group__core__array.html#ga10ac1bfb180e2cfda1701d06c24fdbd6">cv.add</a>(x,y) ) <span class="comment"># 250+10 = 260 =&gt; 255</span></div><div class="line">[[255]]</div><div class="line"></div><div class="line">&gt;&gt;&gt; <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>( x+y )          <span class="comment"># 250+10 = 260 % 256 = 4</span></div><div class="line">[4]</div></div><!-- fragment --><p> This will be more visible when you add two images. Stick with OpenCV functions, because they will provide a better result.</p>
<h2>Image Blending </h2>
<p>This is also image addition, but different weights are given to images in order to give a feeling of blending or transparency. Images are added as per the equation below:</p>
<p class="formulaDsp">
\[g(x) = (1 - \alpha)f_{0}(x) + \alpha f_{1}(x)\]
</p>
<p>By varying \(\alpha\) from \(0 \rightarrow 1\), you can perform a cool transition between one image to another.</p>
<p>Here I took two images to blend together. The first image is given a weight of 0.7 and the second image is given 0.3. <a class="el" href="../../d2/de8/group__core__array.html#gafafb2513349db3bcff51f54ee5592a19" title="Calculates the weighted sum of two arrays. ">cv.addWeighted()</a> applies the following equation to the image:</p>
<p class="formulaDsp">
\[dst = \alpha \cdot img1 + \beta \cdot img2 + \gamma\]
</p>
<p>Here \(\gamma\) is taken as zero. </p><div class="fragment"><div class="line">img1 = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;ml.png&#39;</span>)</div><div class="line">img2 = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;opencv-logo.png&#39;</span>)</div><div class="line"></div><div class="line">dst = <a class="code" href="../../d2/de8/group__core__array.html#gafafb2513349db3bcff51f54ee5592a19">cv.addWeighted</a>(img1,0.7,img2,0.3,0)</div><div class="line"></div><div class="line"><a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(<span class="stringliteral">&#39;dst&#39;</span>,dst)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv.waitKey</a>(0)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga6b7fc1c1a8960438156912027b38f481">cv.destroyAllWindows</a>()</div></div><!-- fragment --><p> Check the result below:</p>
<div class="image">
<img src="../../blending.jpg" alt="blending.jpg"/>
<div class="caption">
image</div></div>
 <h2>Bitwise Operations </h2>
<p>This includes the bitwise AND, OR, NOT, and XOR operations. They will be highly useful while extracting any part of the image (as we will see in coming chapters), defining and working with non-rectangular ROI's, and etc. Below we will see an example of how to change a particular region of an image.</p>
<p>I want to put the OpenCV logo above an image. If I add two images, it will change the color. If I blend them, I get a transparent effect. But I want it to be opaque. If it was a rectangular region, I could use ROI as we did in the last chapter. But the OpenCV logo is a not a rectangular shape. So you can do it with bitwise operations as shown below: </p><div class="fragment"><div class="line"><span class="comment"># Load two images</span></div><div class="line">img1 = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;messi5.jpg&#39;</span>)</div><div class="line">img2 = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;opencv-logo-white.png&#39;</span>)</div><div class="line"></div><div class="line"><span class="comment"># I want to put logo on top-left corner, So I create a ROI</span></div><div class="line">rows,cols,channels = img2.shape</div><div class="line">roi = img1[0:rows, 0:cols]</div><div class="line"></div><div class="line"><span class="comment"># Now create a mask of logo and create its inverse mask also</span></div><div class="line">img2gray = <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cv.cvtColor</a>(img2,cv.COLOR_BGR2GRAY)</div><div class="line">ret, mask = <a class="code" href="../../d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57">cv.threshold</a>(img2gray, 10, 255, cv.THRESH_BINARY)</div><div class="line">mask_inv = <a class="code" href="../../d2/de8/group__core__array.html#ga0002cf8b418479f4cb49a75442baee2f">cv.bitwise_not</a>(mask)</div><div class="line"></div><div class="line"><span class="comment"># Now black-out the area of logo in ROI</span></div><div class="line">img1_bg = <a class="code" href="../../d2/de8/group__core__array.html#ga60b4d04b251ba5eb1392c34425497e14">cv.bitwise_and</a>(roi,roi,mask = mask_inv)</div><div class="line"></div><div class="line"><span class="comment"># Take only region of logo from logo image.</span></div><div class="line">img2_fg = <a class="code" href="../../d2/de8/group__core__array.html#ga60b4d04b251ba5eb1392c34425497e14">cv.bitwise_and</a>(img2,img2,mask = mask)</div><div class="line"></div><div class="line"><span class="comment"># Put logo in ROI and modify the main image</span></div><div class="line">dst = <a class="code" href="../../d2/de8/group__core__array.html#ga10ac1bfb180e2cfda1701d06c24fdbd6">cv.add</a>(img1_bg,img2_fg)</div><div class="line">img1[0:rows, 0:cols ] = dst</div><div class="line"></div><div class="line"><a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(<span class="stringliteral">&#39;res&#39;</span>,img1)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv.waitKey</a>(0)</div><div class="line"><a class="code" href="../../d7/dfc/group__highgui.html#ga6b7fc1c1a8960438156912027b38f481">cv.destroyAllWindows</a>()</div></div><!-- fragment --><p> See the result below. Left image shows the mask we created. Right image shows the final result. For more understanding, display all the intermediate images in the above code, especially img1_bg and img2_fg.</p>
<div class="image">
<img src="../../overlay.jpg" alt="overlay.jpg"/>
<div class="caption">
image</div></div>
 <h2>Additional Resources </h2>
<h2>Exercises </h2>
<ol type="1">
<li>Create a slide show of images in a folder with smooth transition between images using <a class="el" href="../../d2/de8/group__core__array.html#gafafb2513349db3bcff51f54ee5592a19" title="Calculates the weighted sum of two arrays. ">cv.addWeighted</a> function </li>
</ol>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:37 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
